package cn.hist.hfp.service;

import cn.hist.hfp.RoleType;
import cn.hist.hfp.entity.Manager;
import cn.hist.hfp.entity.ManagerValidation;
import cn.hist.hfp.entity.User;
import cn.hist.hfp.entity.UserValidation;
import cn.hist.hfp.exception.BusinessException;
import cn.hist.hfp.exception.ErrorCode;
import cn.hist.hfp.repository.ManagerValidationRepository;
import cn.hist.hfp.repository.UserValidationRepository;
import cn.hist.hfp.util.TokenUtil;
import cn.hist.hfp.vo.ManagerLoginVO;
import cn.hist.hfp.vo.UserLoginVO;
import cn.hist.hfp.vo.ValidationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AuthService {

    private final
    UserService userService;

    private final
    ManagerService managerService;

    private final UserValidationRepository userValidationRepository;

    private final ManagerValidationRepository managerValidationRepository;


    private final TokenUtil tokenUtil;

    @Autowired
    public AuthService(UserService userService, ManagerService managerService, TokenUtil tokenUtil,
                       UserValidationRepository userValidationRepository,
                       ManagerValidationRepository managerValidationRepository) {
        this.userService = userService;
        this.managerService = managerService;
        this.tokenUtil = tokenUtil;
        this.userValidationRepository = userValidationRepository;
        this.managerValidationRepository = managerValidationRepository;
    }

    public ValidationVO reLogin(String token) {
        String identity = tokenUtil.getIdentityInfo(token);
        String role = identity.split(" ")[0];
        int id = Integer.parseInt(identity.split(" ")[1]);

        if (role.equals(RoleType.USER.getName())) {
            User user = userService.findOne(id);
            return generateUserValidation(user, token);
        } else {
            Manager manager = managerService.findOne(id);
            return ValidationVO.builder()
                    .id(id).name(manager.getName()).role(RoleType.MANAGER.getName()).token(token).validated(true).build();
        }
    }


    public ValidationVO userLogin(UserLoginVO loginVO) {
        User user = userService.findByLoginNameAndPassword(loginVO.getLoginName(), loginVO.getPassword());
        if (user == null)
            throw new BusinessException(ErrorCode.VALIDATION_FAILED);

        String token = tokenUtil.generateToken(RoleType.USER.getName() + " " + user.getId());

        UserValidation userValidation = user.getValidation();
        if (userValidation != null) {
            userValidation.setToken(token);
        } else {
            userValidation = userValidationRepository.save(new UserValidation(user, token));
        }
        user.setValidation(userValidation);
        User storedUser = userService.update(user);

        return generateUserValidation(storedUser, token);
    }

    public ValidationVO generateUserValidation(User user, String token) {

        return ValidationVO.builder()
                .id(user.getId())
                .name(user.getName())
                .role(RoleType.USER.getName())
                .token(token)
                .validated(true)
                .build();
    }

    public ValidationVO generateEmptyUserValidation() {
        return ValidationVO.builder()
                .id(-1)
                .name("")
                .role("")
                .token("")
                .validated(false)
                .build();
    }


    public ValidationVO userLogout(ValidationVO validationVO) {

        userValidationRepository.deleteById(validationVO.getId());

        return generateEmptyUserValidation();
    }

    public ValidationVO managerLogin(ManagerLoginVO loginVO) {
        Manager manager = managerService.findByLoginNameAndPassword(loginVO.getLoginName(), loginVO.getPassword());
        if (manager == null)
            throw new BusinessException(ErrorCode.VALIDATION_FAILED);

        String token = tokenUtil.generateToken(RoleType.MANAGER.getName() + " " + manager.getId());

        ManagerValidation managerValidation = manager.getValidation();
        if (managerValidation != null) {
            managerValidation.setToken(token);
        } else {
            managerValidation = managerValidationRepository.save(new ManagerValidation(manager, token));
        }
        manager.setValidation(managerValidation);
        Manager storedManager = managerService.update(manager);

        return ValidationVO.builder()
                .id(storedManager.getId())
                .name(storedManager.getName())
                .role(RoleType.MANAGER.getName())
                .token(token)
                .validated(true)
                .build();
    }

    public ValidationVO managerLogout(ValidationVO validationVO) {

        managerValidationRepository.deleteById(validationVO.getId());

        return generateEmptyUserValidation();
    }
}
